package com.chenju.easyshotjava.core;

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;

public class EasyShot extends JFrame implements NativeKeyListener {
    // 获取日志实例
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(EasyShot.class);

    private JComboBox<String> testCaseComboBox;
    private List<String> testCases;
    private JButton startButton;
    private JButton finishButton;
    private JButton reportButton;
    private JButton fullScreenButton;
    private JButton regionButton;
    private JButton clearButton;
    private final Map<String, KeyStroke> keyBindings;
    // 存储快捷键
    private final Map<String, Runnable> actions;
    private int currentIndex = 0;
    private int screenshotIndex = 1; // 用于生成连续的截图序号

    public EasyShot() {
        keyBindings = new HashMap<>();
        actions = new HashMap<>();

        logger.info("加载input文件…");
        loadTestCasesFromFile("input");

        logger.info("初始化UI界面…");
        setupUI();

        logger.info("初始化按钮操作…");
        setupActions();

        logger.info("初始化全局快捷键操作…");
        // 初始化全局快捷键操作
        setupGlobalActions();

        logger.info("初始化全局键盘输入监听…");
        // 初始化全局键盘输入监听
        setupGlobalKeyListener();

        logger.info("加载本地化快捷键数据…");
        loadKeyBindings();

        logger.info("初始化截图目录…");
        setupImagesDir();
    }

    private void setupUI() {
        setTitle("截图工具");
        setAlwaysOnTop(true);
        createMenuBar();
        setSize(350, 140);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout()); // 使用 BorderLayout 管理整体布局

        // 上部区域（第一行）
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
        testCaseComboBox = new JComboBox<>(testCases.toArray(new String[0]));
        testCaseComboBox.setPreferredSize(new Dimension(200, 25));
        testCaseComboBox.setRenderer(new CustomListCellRenderer());
        startButton = new JButton("开始");
        clearButton = new JButton("重置");
        topPanel.add(testCaseComboBox);
        topPanel.add(startButton);
//        topPanel.add(clearButton);

        // 下部区域（第二行）
        JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
        fullScreenButton = new JButton("全屏");
        regionButton = new JButton("区域");
        finishButton = new JButton("完成");
        reportButton = new JButton("报告");
        bottomPanel.add(fullScreenButton);
        bottomPanel.add(regionButton);
        bottomPanel.add(finishButton);
        bottomPanel.add(reportButton);

        // 添加到主窗口
        add(topPanel, BorderLayout.NORTH);
        add(bottomPanel, BorderLayout.SOUTH);
    }

    private void setupGlobalActions() {
        actions.put("finish", () -> {
            SwingUtilities.invokeLater(this::finishTestCase);
        });
        actions.put("fullscreen", () -> {
            SwingUtilities.invokeLater(this::takeFullScreenShot);
        });
    }

    private void setupGlobalKeyListener() {
        try {
            // 禁用 JNativeHook 的日志输出
            Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
            logger.setLevel(Level.OFF);

            // 注册全局事件监听器
            GlobalScreen.registerNativeHook();
            GlobalScreen.addNativeKeyListener(this);
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this,
                    "全局快捷键注册失败: " + e.getMessage(),
                    "错误",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent e) {
        // 获取按键组合
        int modifiers = e.getModifiers();
        String keyText = NativeKeyEvent.getKeyText(e.getKeyCode());

        // 遍历所有快捷键绑定
        for (Map.Entry<String, KeyStroke> entry : keyBindings.entrySet()) {
            KeyStroke ks = entry.getValue();
            if (ks != null) {
                // 检查修饰键是否匹配
                boolean modifiersMatch =
                        ((modifiers & NativeKeyEvent.CTRL_MASK) != 0) == ((ks.getModifiers() & KeyEvent.CTRL_DOWN_MASK) != 0) &&
                        ((modifiers & NativeKeyEvent.SHIFT_MASK) != 0) == ((ks.getModifiers() & KeyEvent.SHIFT_DOWN_MASK) != 0) &&
                        ((modifiers & NativeKeyEvent.ALT_MASK) != 0) == ((ks.getModifiers() & KeyEvent.ALT_DOWN_MASK) != 0);

                // 检查主键是否匹配
                boolean keyMatch = keyText.equalsIgnoreCase(KeyEvent.getKeyText(ks.getKeyCode()));

                if (modifiersMatch && keyMatch) {
                    // 执行对应的操作
                    Runnable action = actions.get(entry.getKey());
                    if (action != null) {
                        action.run();
                    }
                }
            }
        }
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent e) {
        // 不需要实现
    }

    @Override
    public void nativeKeyTyped(NativeKeyEvent e) {
        // 不需要实现
    }

    // 在窗口关闭时注销全局监听器
    private void cleanup() {
        try {
            GlobalScreen.unregisterNativeHook();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void dispose() {
        cleanup();
        super.dispose();
    }

    private void setupActions() {
        startButton.addActionListener(e -> startTestCase());
        finishButton.addActionListener(e -> finishTestCase());
        reportButton.addActionListener(e -> generateReport());
        fullScreenButton.addActionListener(e -> takeFullScreenShot());
        regionButton.addActionListener(e -> takeRegionShot());
        clearButton.addActionListener(e -> clearPreference());
    }

    /**
     * 处理文件选择
     */
    private void handleFileSelection() {
        // 持久化
        Preferences prefs = Preferences.userNodeForPackage(EasyShot.class);
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择输入文件");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setCurrentDirectory(new File(prefs.get("lastSelectedDir", System.getProperty("user.dir"))));

        // 设置文件过滤器，仅允许选择 .xlsx 和 .docx 文件
        fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().endsWith(".xlsx") || f.getName().endsWith(".docx");
            }

            @Override
            public String getDescription() {
                return "Excel 文件 (*.xlsx), Word 文件 (*.docx)";
            }
        });

        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            String fileName = selectedFile.getAbsolutePath();
            prefs.put("lastSelectedDir", selectedFile.getParent());
            loadTestCasesFromSelectedFile(fileName);
        }
    }

    private void loadTestCasesFromSelectedFile(String fileName) {
        testCases.clear(); // 清空之前的测试用例
        if (fileName.endsWith(".xlsx") || fileName.endsWith(".docx")) {
            loadTestCasesFromFile(fileName);
        } else {
            JOptionPane.showMessageDialog(this, "不支持的文件类型！", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 更新测试用例选择框
        updateTestCaseComboBox();

        JOptionPane.showMessageDialog(this, "成功加载测试用例：" + testCases.size() + " 条！");

    }

    /**
     * 更新 JComboBox 的数据模型
     */
    private void updateTestCaseComboBox() {
        // 创建新的数据模型
        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>(testCases.toArray(new String[0]));
        // 设置新的数据模型到 JComboBox
        testCaseComboBox.setModel(model);
    }

    private void loadKeyBindings() {
        Preferences prefs = Preferences.userNodeForPackage(EasyShot.class);
        keyBindings.put("start", KeyStrokeUtils.stringToKeyStroke(prefs.get("start", "F1")));
        keyBindings.put("finish", KeyStrokeUtils.stringToKeyStroke(prefs.get("finish", "F8")));
        keyBindings.put("fullscreen", KeyStrokeUtils.stringToKeyStroke(prefs.get("fullscreen", "F7")));
        keyBindings.put("region", KeyStrokeUtils.stringToKeyStroke(prefs.get("region", "F9")));
        keyBindings.put("report", KeyStrokeUtils.stringToKeyStroke(prefs.get("report", "F2")));

        updateKeyBindings();
    }

    private void createMenuBar() {
        JMenuBar menuBar = new JMenuBar();

        // 文件菜单
        JMenu fileMenu = new JMenu("文件");
        JMenuItem selectFile = new JMenuItem("选择文件");
        selectFile.addActionListener(e -> handleFileSelection());

        fileMenu.add(selectFile);

        // 帮助菜单
        JMenu helpMenu = new JMenu("帮助");
        JMenuItem shotItem = new JMenuItem("快捷键信息");
        shotItem.addActionListener(e -> showShotDialog());
        JMenuItem useItem = new JMenuItem("使用说明");
        useItem.addActionListener(e -> showUseDialog());

        helpMenu.add(shotItem);
        helpMenu.add(useItem);

        // 设置菜单
        JMenu settingMenu = new JMenu("设置");
        JMenuItem shotSetItem = new JMenuItem("快捷键设置");
        shotSetItem.addActionListener(e -> showShotSetDialog());
        settingMenu.add(shotSetItem);

        menuBar.add(fileMenu);
        menuBar.add(settingMenu);
        menuBar.add(helpMenu);

        setJMenuBar(menuBar);
    }

    private void setupImagesDir() {
        File imagesDir = new File("images");
        if (!imagesDir.exists()) {
            if (imagesDir.mkdir()) {
                logger.info(String.format("已创建images目录: %s", imagesDir.getAbsolutePath()));
            } else {
                logger.error("无法创建images目录");
                JOptionPane.showMessageDialog(this, "无法创建images目录, 请检查或着手动创建");
            }
        }
    }

    private void showShotDialog() {
        StringBuilder message = new StringBuilder();

        message.append("开始: ").append(KeyStrokeUtils.keyStrokeToString(keyBindings.get("start"))).append(" (仅选中)\n");
        message.append("完成: ").append(KeyStrokeUtils.keyStrokeToString(keyBindings.get("finish"))).append(" (支持全局)\n");
        message.append("全屏: ").append(KeyStrokeUtils.keyStrokeToString(keyBindings.get("fullscreen"))).append(" (支持全局)\n");
        message.append("区域: ").append(KeyStrokeUtils.keyStrokeToString(keyBindings.get("region"))).append(" (仅选中)\n");
        message.append("报告: ").append(KeyStrokeUtils.keyStrokeToString(keyBindings.get("report"))).append(" (仅选中)\n");

        JOptionPane.showMessageDialog(this, message.toString(), "快捷键信息", JOptionPane.INFORMATION_MESSAGE);
    }

    private void showUseDialog() {
        StringBuilder message = new StringBuilder();
        message.append("- 操作步骤\n");
        message.append("  - 使用下拉框选择测试用例\n");
        message.append("  - 点击按钮或使用快捷键进行操作\n");
        message.append("  - 通过“设置快捷键”按钮可自定义快捷键\n\n\n");

        message.append("- 按钮功能说明\n");
        message.append("  - 开始: 从当前案例开始截图\n");
        message.append("  - 全屏: 全屏截图\n");
        message.append("  - 区域: 自定义截图, 支持标注\n");
        message.append("  - 完成: 本条案例执行结束, 开始执行下一条\n");
        message.append("  - 报告: 生成证件文件(编号模式), 支持导入平台\n\n\n");


        message.append("- 菜单说明\n");
        message.append("  - 文件\n");
        message.append("    - 选择文件: 选择用例文件, 支持docx/xlsx文件\n");
        message.append("  - 设置\n");
        message.append("    - 快捷键设置: 设置操作快捷键\n");
        message.append("  - 帮助\n");
        message.append("    - 快捷键信息: 显示设置的快捷键信息\n");
        message.append("    - 使用说明: 显示详细使用说明信息\n");

        JOptionPane.showMessageDialog(this, message.toString(), "使用提示", JOptionPane.INFORMATION_MESSAGE);
    }

    private void showShotSetDialog() {
        JDialog dialog = new JDialog(this, "快捷键设置", true);
        dialog.setLayout(new GridLayout(6, 2));
        dialog.setSize(300, 200);

        JLabel startLabel = new JLabel("开始 ( 仅选中 ):");
        JLabel finishLabel = new JLabel("完成 (支持全局):");
        JLabel fullscreenLabel = new JLabel("全屏 (支持全局):");
        JLabel regionLabel = new JLabel("区域 ( 仅选中 ):");
        JLabel reportLabel = new JLabel("报告 ( 仅选中 ):");

        JTextField startKey = new JTextField(KeyStrokeUtils.keyStrokeToString(keyBindings.get("start")));
        JTextField finishKey = new JTextField(KeyStrokeUtils.keyStrokeToString(keyBindings.get("finish")));
        JTextField fullscreenKey = new JTextField(KeyStrokeUtils.keyStrokeToString(keyBindings.get("fullscreen")));
        JTextField regionKey = new JTextField(KeyStrokeUtils.keyStrokeToString(keyBindings.get("region")));
        JTextField reportKey = new JTextField(KeyStrokeUtils.keyStrokeToString(keyBindings.get("report")));

        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> {
            keyBindings.put("start", KeyStrokeUtils.stringToKeyStroke(startKey.getText()));
            keyBindings.put("finish", KeyStrokeUtils.stringToKeyStroke(finishKey.getText()));
            keyBindings.put("fullscreen", KeyStrokeUtils.stringToKeyStroke(fullscreenKey.getText()));
            keyBindings.put("region", KeyStrokeUtils.stringToKeyStroke(regionKey.getText()));
            keyBindings.put("report", KeyStrokeUtils.stringToKeyStroke(reportKey.getText()));
            updateKeyBindings();

            saveKeyBindings();
            dialog.dispose();
        });

        dialog.add(startLabel);
        dialog.add(startKey);
        dialog.add(finishLabel);
        dialog.add(finishKey);
        dialog.add(fullscreenLabel);
        dialog.add(fullscreenKey);
        dialog.add(regionLabel);
        dialog.add(regionKey);
        dialog.add(reportLabel);
        dialog.add(reportKey);
        dialog.add(new JLabel()); // 占位
        dialog.add(saveButton);
        dialog.setVisible(true);
    }

    private void saveKeyBindings() {
        Preferences prefs = Preferences.userNodeForPackage(EasyShot.class);
        prefs.put("start", KeyStrokeUtils.keyStrokeToString(keyBindings.get("start")));
        prefs.put("finish", KeyStrokeUtils.keyStrokeToString(keyBindings.get("finish")));
        prefs.put("fullscreen", KeyStrokeUtils.keyStrokeToString(keyBindings.get("fullscreen")));
        prefs.put("region", KeyStrokeUtils.keyStrokeToString(keyBindings.get("region")));
        prefs.put("report", KeyStrokeUtils.keyStrokeToString(keyBindings.get("report")));
    }

    /**
     * 本地快捷键
     */
    private void updateKeyBindings() {
        JRootPane rootPane = this.getRootPane();
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = rootPane.getActionMap();

        inputMap.clear();
        actionMap.clear();

        inputMap.put(keyBindings.get("start"), "start");
        actionMap.put("start", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 实现开始功能
                startTestCase();
            }
        });

        inputMap.put(keyBindings.get("region"), "region");
        actionMap.put("region", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 实现区域截图功能
                takeRegionShot();
            }
        });

        inputMap.put(keyBindings.get("report"), "report");
        actionMap.put("report", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 实现区域截图功能
                generateReport();
            }
        });
    }

    /**
     * 开始按钮
     * 当选择了案例编号并点击开始按钮，此时将全局index修改为选择的案例并重置截图序号
     */
    private void startTestCase() {
        currentIndex = testCaseComboBox.getSelectedIndex();
        screenshotIndex = 1; // 重置截图序号
        if (testCaseComboBox != null) {
            logger.info(String.format("点击开始按钮执行案例: %s", testCaseComboBox.getSelectedItem()));
        }
    }

    /**
     * 完成按钮
     * 当前序列号+1并重置截图序号
     */
    private void finishTestCase() {
        currentIndex++;
        screenshotIndex = 1; // 重置截图序号
        if (currentIndex < testCases.size()) {
            testCaseComboBox.setSelectedIndex(currentIndex);
        } else {
            JOptionPane.showMessageDialog(this, "所有测试用例已执行完毕");
        }
        logger.info("点击完成按钮执行下一条案例");
    }

    /**
     * 全屏截图
     * Step1: 验证currentIndex和下拉框中的index
     * Step2: 截图时自动隐藏面板
     */
    private void takeFullScreenShot() {
        if (currentIndex != testCaseComboBox.getSelectedIndex()) {
            JOptionPane.showMessageDialog(this, "请点击【开始】按钮");
            return;
        }
        try {
            setVisible(false); // 隐藏UI界面
            Thread.sleep(500); // 确保界面隐藏后再截图

            Robot robot = new Robot();
            Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
            BufferedImage screenFullImage = robot.createScreenCapture(screenRect);

            String testCaseId = (String) testCaseComboBox.getSelectedItem();
            String fileName = "images/" + testCaseId + "-" + String.format("%03d", screenshotIndex++) + ".png";
            File outputFile = new File(fileName);
            ImageIO.write(screenFullImage, "png", outputFile);

            logger.info(String.format("全屏截图已保存: %s", fileName));

            // JOptionPane.showMessageDialog(this, "全屏截图已保存: " + outputFile.getName());
            showAutoDismissDialog("全屏截图已保存: " + outputFile.getName());
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error(ex.getMessage());
        } finally {
            setVisible(true); // 恢复UI界面显示
        }
    }

    /**
     * 区域截图
     * Step1: 验证currentIndex和下拉框中的index
     * Step2: 截图时自动隐藏面板
     * Step3: 标注区域
     * Step4: 保存截图
     */
    private void takeRegionShot() {
        if (currentIndex != testCaseComboBox.getSelectedIndex()) {
            JOptionPane.showMessageDialog(this, "请点击【开始】按钮");
            return;
        }
        try {
            setVisible(false); // 隐藏UI界面
            Thread.sleep(500); // 确保界面隐藏后再截图

            // 创建一个全屏窗口用于选择截图区域
            JWindow window = new JWindow();
            window.setOpacity(0.5f);
            window.setBackground(Color.GRAY);
            window.setAlwaysOnTop(true);
            window.setSize(Toolkit.getDefaultToolkit().getScreenSize());

            RectangleCapture capture = new RectangleCapture(window);
            window.add(capture);
            window.setVisible(true);

            // 等待用户完成区域选择
            capture.addCaptureListener(rect -> {
                window.setVisible(false); // 区域选择完成后，隐藏窗口

                try {
                    Robot robot = new Robot();
                    BufferedImage screenRegionImage = robot.createScreenCapture(rect);

                    // 显示并允许标注
                    markImage(screenRegionImage, rect);

                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    setVisible(true); // 恢复UI界面显示
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 标注框
     * @param image
     * @param captureRect
     */
    private void markImage(BufferedImage image, Rectangle captureRect) {
        JFrame frame = new JFrame("标注截图");
        frame.setSize(captureRect.width + 20, captureRect.height + 60);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.setLocationRelativeTo(null);

        ImagePanel imagePanel = new ImagePanel(image);
        frame.add(imagePanel, BorderLayout.CENTER);

        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> {
            try {
                String testCaseId = (String) testCaseComboBox.getSelectedItem();
                String fileName = "images/" + testCaseId + "-" + String.format("%03d", screenshotIndex++) + ".png";
                File outputFile = new File(fileName);
                ImageIO.write(image, "png", outputFile);
                logger.info(String.format("区域截图已保存: %s", fileName));

                showAutoDismissDialog("标注截图已保存: " + outputFile.getName());
                frame.dispose();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });

        JPanel controlPanel = new JPanel();
        controlPanel.add(saveButton);
        frame.add(controlPanel, BorderLayout.SOUTH);

        frame.setVisible(true);
    }

    /**
     * 报告生成
     * 添加图片并设置标题格式
     */
    public void generateReport() {

        // 记录当前时间
        long currentTimeMillis = System.currentTimeMillis();

        try (XWPFDocument doc = new XWPFDocument()) {
            // 创建样式
            WordUtils.createCustomStyle(doc, "2", "Heading 1");
            // 添加顶部文字
            XWPFParagraph topParagraph = doc.createParagraph();
            XWPFRun topRun = topParagraph.createRun();
            topRun.setText("analise-mode=case-code");
            topRun.addCarriageReturn(); // 添加换行符

            for (String testCase : testCases) {
                // 添加测试用例编号作为标题1
                XWPFParagraph paragraph = doc.createParagraph();
                paragraph.setStyle("2"); // 应用样式
                XWPFRun run = paragraph.createRun();
                run.setText(testCase);

                // 插入该测试用例的所有截图
                int imageIndex = 1;
                while (true) {
                    String imagePath = "images/" + testCase + "-" + String.format("%03d", imageIndex) + ".png";
                    File imgFile = new File(imagePath);
                    if (!imgFile.exists()) {
                        break; // 如果文件不存在，停止查找更多图片
                    }

                    try (FileInputStream is = new FileInputStream(imgFile)) {
                        XWPFParagraph imgParagraph = doc.createParagraph();
                        XWPFRun imgRun = imgParagraph.createRun();
                        imgRun.addCarriageReturn();
                        WordUtils.addPictureToTestCase(imgRun, imagePath, is, 400);
//                        WordImageHelper.addPicture(imgRun, imagePath, is, 400);
                    }
                    imageIndex++;
                }
            }

            // 生成证迹文件
            String filename = "证迹文件" + currentTimeMillis + ".docx";
            try (FileOutputStream out = new FileOutputStream(filename)) {
                doc.write(out);
                out.flush();
                logger.info(String.format("证迹文件已生成: %s", filename));

                JOptionPane.showMessageDialog(this, "证迹文件已生成");
            } finally {
                doc.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error(ex.getMessage());
        }

        // 创建备份文件
        // 获取当前工作目录
        Path currentDir = Paths.get(System.getProperty("user.dir"));
        // 定义源目录和目标目录
        Path sourceDir = currentDir.resolve("images");
        Path targetDir = currentDir.resolve("backup/" + currentTimeMillis);

        // 调用方法复制images目录
        copyDirectory("images", "backup/" + currentTimeMillis);
        logger.info(String.format("截图已由【%s】到【%s】备份完成", sourceDir, targetDir));

        // 删除images文件夹
        deleteDirectory(new File("images"));
        logger.info("目录【images】已清空");
    }

    public static Set<String> foundDuplicateCaseCodes(List<String> testCases) {
        // 使用 Map 分组统计并提取出现多次的元素
        Set<String> duplicates = testCases.stream()
                .collect(Collectors.groupingBy(e -> e, Collectors.counting())) // 统计每个元素的出现次数
                .entrySet().stream()
                .filter(entry -> entry.getValue() > 1) // 过滤出出现多次的元素
                .map(Map.Entry::getKey) // 提取键（元素本身）
                .collect(Collectors.toSet()); // 收集为 Set
        if (!testCases.isEmpty() && !duplicates.isEmpty()){
            logger.warn(String.format("重复的CaseCode: %s", duplicates));
        }
        return duplicates;
    }

    /**
     * 复制目录及其内容
     *
     * @param sourceDir 源目录
     * @param targetDir 目标目录
     */
    public static void copyDirectory(String sourceDir, String targetDir) {
        // 定义源文件夹和目标文件夹的路径
        Path source = Paths.get(sourceDir);
        Path target = Paths.get(targetDir);

        // 检查源文件夹是否存在
        if (!Files.exists(source) || !Files.isDirectory(source)) {
            logger.warn(String.format("源目录不存在或者不是文件夹: %s", source.toAbsolutePath()));
            return;
        }

        try {
            // 如果目标目录不存在，创建目标目录
            if (!Files.exists(target)) {
                Files.createDirectories(target);
            }

            // 遍历源目录中的所有文件
            DirectoryStream<Path> directoryStream = Files.newDirectoryStream(source);
            for (Path file : directoryStream) {
                if (Files.isRegularFile(file)) { // 确保是文件而不是子目录
                    Path targetFile = target.resolve(file.getFileName());
                    Files.copy(file, targetFile, StandardCopyOption.REPLACE_EXISTING);
                }
            }
        } catch (IOException e) {
            e.printStackTrace(); // 打印异常信息
            logger.error(e.getMessage());
        }
    }

    /**
     * 删除目录中的所有文件和子目录
     *
     * @param directory 要清空的目录
     */
    public static void deleteDirectory(File directory) {
        // 获取目录中的所有文件和子目录
        File[] files = directory.listFiles();
        if (files != null) { // 防止空指针异常（如目录为空）
            for (File file : files) {
                // 删除文件或空目录
                if (!file.delete()) {
                    logger.error(String.format("无法删除文件或目录: %s", file.getAbsolutePath()));
                }
            }
        }
    }

    public void clearPreference() {
        Preferences prefs = Preferences.userNodeForPackage(EasyShot.class);

        // 清空 Preferences 中的数据
        try {
            prefs.clear();
            logger.info("清空所有的用户设置");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }

    // 自定义 ListCellRenderer
    static class CustomListCellRenderer extends DefaultListCellRenderer {
        private final int MAX_LENGTH = 18;  // 设置文本最大显示长度

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            if (value instanceof String) {
                String text = (String) value;
                if (text.length() > MAX_LENGTH) {
                    int ellipsisIndex = MAX_LENGTH / 2;
                    String shortenedText = text.substring(0, ellipsisIndex) + "..." + text.substring(text.length() - ellipsisIndex);
                    setText(shortenedText);
                } else {
                    setText(text);
                }
            }

            return this;
        }
    }

    /**
     * 提示框
     * @param message
     */
    private void showAutoDismissDialog(String message) {
        JDialog dialog = new JDialog(this, "提示", false);
        dialog.setLayout(new FlowLayout());
        dialog.add(new JLabel(message));
        dialog.pack();
        dialog.setMaximumSize(new Dimension(400, 100));
        dialog.setLocationRelativeTo(this);
        dialog.setVisible(true);

        // 设置1秒后自动关闭
        Timer timer = new Timer(1000, e -> dialog.setVisible(false));
        timer.setRepeats(false);
        timer.start();
    }

    /**
     * 加载本地文件获取测试用例编号
     * @param fileName
     */
    private void loadTestCasesFromFile(String fileName) {
        TestCaseLoader loader = new TestCaseLoader();
        testCases = loader.loadTestCaseIds(fileName);
        Set<String> set = foundDuplicateCaseCodes(testCases);
        if (!testCases.isEmpty() && !set.isEmpty()) {
            JOptionPane.showMessageDialog(this, String.format("存在重复的测试用例编号,生成证迹文件将会出错,请先修改案例编号后使用!\n\n重复的编号:\n%s", ListUtils.toString(set.stream().toList())));
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new EasyShot().setVisible(true));
    }
}